using System;
using System.Collections.Generic;
using UmengAnalyticsNet.Extension;
using UmengAnalyticsNet.Interface;
using UmengSDK.Business;
using UmengSDK.Common;
using UmengSDK.Model;

namespace UmengSDK
{
    public partial class UmengAnalytics : IAppHandler
    {
        private static IInformation _information;
        private static IAnalyticsApplication _application;

        public delegate void UpdateEventHandler(int statusCode, UpdateEventArgs e);

        public delegate void OnlineParamHandler(int statusCode, OnlineParamEventArgs e);

        private static bool _initSuccessed;

        private static int MAX_LENGTH_30;

        private static Manager _manager;

        private static UpdateManager _updateMgr;

        private static OnlineParamManager _onlineParamMgr;

        public static event UpdateEventHandler CheckUpdateCompleted;

        public static event OnlineParamHandler UpdateOnlineParamCompleted;

        public static string NumberKey
        {
            get
            {
                return "__ct__";
            }
        }

        public static bool IsDebug
        {
            get
            {
                return Constants.IsDebug;
            }
            set
            {
                Constants.IsDebug = value;
            }
        }

        static UmengAnalytics()
        {
            _initSuccessed = true;
            MAX_LENGTH_30 = 30;
            _manager = null;
            _updateMgr = null;
            _onlineParamMgr = null;
        }

        private static void Init()
        {
            try
            {
                _manager = new Manager();
                _updateMgr = new UpdateManager();
                _onlineParamMgr = new OnlineParamManager();
                _onlineParamMgr.UpdateCompletedEvent = OnlineParamCallback;
                _updateMgr.CheckCompletedEvent = OnCheckUpdateCompleted;
            }
            catch (Exception e)
            {
                _initSuccessed = false;
                DebugUtil.Log("UmengAnalytics constructor failed!", e);
            }
        }

        public static void Initialize(string appkey, IInformation p_information, IAnalyticsApplication p_application, string channel = "Marketplace")
        {
            _information = p_information;
            _application = p_application;

            if (_information == null)
            {
                throw new ArgumentNullException("p_information");
            }

            Header.Information = _information;

            try
            {
                if (_initSuccessed)
                {
                    if (!IsValidAppkey(appkey))
                    {
                        DebugUtil.Log("Invalid app key!");
                    }
                    else
                    {
                        if (!string.IsNullOrEmpty(channel))
                        {
                            channel = channel.CheckInput(MAX_LENGTH_30);
                            Manager.Channel = channel;
                        }
                        Manager.AppKey = appkey;
                        Init();
                        UmengSettings.Load();
                        RegisterEvents();
                        DebugUtil.Log("UmengAnalytics Init completed!");
                    }
                }
            }
            catch (Exception e)
            {
                _initSuccessed = false;
                DebugUtil.Log("Umeng SDK init failed!", e);
            }
        }

        public static void TrackPageStart(string pageName)
        {
            try
            {
                if (_initSuccessed && IsValidInput(pageName))
                {
                    pageName = pageName.CheckInput(256);
                    _manager.AddPageViewStart(pageName);
                    DebugUtil.Log(string.Format("TrackPageStart : {0}", pageName));
                }
            }
            catch (Exception e)
            {
                DebugUtil.Log(e);
            }
        }

        public static void TrackPageEnd(string pageName)
        {
            try
            {
                if (_initSuccessed && IsValidInput(pageName))
                {
                    pageName = pageName.CheckInput(256);
                    _manager.AddPageViewEnd(pageName);
                    DebugUtil.Log(string.Format("TrackPageEnd : {0}", pageName));
                }
            }
            catch (Exception e)
            {
                DebugUtil.Log(e);
            }
        }

        public static void TrackEvent(string eventId)
        {
            try
            {
                if (_initSuccessed && IsValidInput(eventId))
                {
                    _manager.AddEvent(eventId);
                    DebugUtil.Log(string.Format("TrackEvent : {0}", eventId));
                }
            }
            catch (Exception e)
            {
                DebugUtil.Log(e);
            }
        }

        public static void TrackEvent(string eventId, string label)
        {
            try
            {
                if (_initSuccessed && IsValidInput(eventId) && IsValidInput(label))
                {
                    _manager.AddEvent(eventId, label);
                    DebugUtil.Log(string.Format("TrackEvent - id:{0} label:{1}", eventId, label));
                }
            }
            catch (Exception e)
            {
                DebugUtil.Log(e);
            }
        }

        public static void TrackEvent(string eventId, long duration)
        {
            try
            {
                if (duration <= 0L)
                {
                    DebugUtil.Log(string.Format("duration can't be less than or equal to 0:{0}", duration));
                }
                else if (_initSuccessed && IsValidInput(eventId))
                {
                    _manager.AddEvent(eventId, duration);
                    DebugUtil.Log(string.Format("TrackEventDuration - id:{0} duration:{1}", eventId, duration));
                }
            }
            catch (Exception e)
            {
                DebugUtil.Log(e);
            }
        }

        public static void TrackEvent(string eventId, string label, long duration)
        {
            try
            {
                if (duration <= 0L)
                {
                    DebugUtil.Log(string.Format("duration can't be less than or equal to 0:{0}", duration));
                }
                else if (_initSuccessed && IsValidInput(eventId) && IsValidInput(label))
                {
                    _manager.AddEvent(eventId, label, duration);
                    DebugUtil.Log(string.Format("TrackEventDuration - id:{0} label:{1} duration:{2}", eventId, label, duration));
                }
            }
            catch (Exception e)
            {
                DebugUtil.Log(e);
            }
        }

        public static void TrackEvent(string eventId, Dictionary<string, string> kv)
        {
            try
            {
                if (_initSuccessed && IsValidInput(eventId) && kv != null && kv.Count > 0)
                {
                    _manager.AddEvent(eventId, kv);
                    DebugUtil.Log(string.Format("TrackEvent - id:{0} kv:{1}", eventId, kv.ToString()));
                }
            }
            catch (Exception e)
            {
                DebugUtil.Log(e);
            }
        }

        public static void TrackEvent(string eventId, Dictionary<string, string> kv, long duration)
        {
            try
            {
                if (duration <= 0L)
                {
                    DebugUtil.Log(string.Format("duration can't be less than or equal to 0:{0}", duration));
                }
                else if (_initSuccessed && IsValidInput(eventId) && kv != null && kv.Count > 0)
                {
                    _manager.AddEvent(eventId, kv, duration);
                    DebugUtil.Log(string.Format("TrackEventDuration - id:{0} duration:{1} kv:{2}", eventId, duration, kv.ToString()));
                }
            }
            catch (Exception e)
            {
                DebugUtil.Log(e);
            }
        }

        public static void TrackError(string error)
        {
            try
            {
                if (_initSuccessed && IsValidInput(error))
                {
                    _manager.AddError(error);
                    DebugUtil.Log(string.Format("TrackError - {0}", error));
                }
            }
            catch (Exception e)
            {
                DebugUtil.Log(e);
            }
        }

        public static void TrackException(Exception ex, string errMsg = "")
        {
            try
            {
                if (_initSuccessed && IsValidInput(ex))
                {
                    _manager.AddError(ex, errMsg);
                    DebugUtil.Log(string.Format("TrackException - {0}", ex.Message));
                }
            }
            catch (Exception e)
            {
                DebugUtil.Log(e);
            }
        }

        public static void UpdateOnlineParamAsync()
        {
            try
            {
                if (_onlineParamMgr != null && IsValidAppkey(Manager.AppKey))
                {
                    _onlineParamMgr.Update();
                }
                else
                {
                    DebugUtil.Log("UpdateOnlineParamAsync:AppKey can't be null, please call Init() first!");
                }
            }
            catch (Exception e)
            {
                DebugUtil.Log(e);
            }
        }

        public static string GetOnlineParam(string key)
        {
            string result;
            try
            {
                if (_onlineParamMgr != null && IsValidInput(key))
                {
                    result = _onlineParamMgr.GetParam(key);
                }
                else
                {
                    result = string.Empty;
                }
            }
            catch (Exception e)
            {
                DebugUtil.Log(e);
                result = string.Empty;
            }
            return result;
        }

        public static void CheckUpdateAsync()
        {
            try
            {
                if (_updateMgr != null && IsValidAppkey(Manager.AppKey))
                {
                    _updateMgr.CheckUpdate();
                }
                else
                {
                    DebugUtil.Log("CheckUpdateAsync:AppKey can't be null, please call Init() first!");
                }
            }
            catch (Exception e)
            {
                DebugUtil.Log(e);
            }
        }

        public static void SetSessionInterval(long seconds)
        {
            Constants.SessionInterval = seconds;
            DebugUtil.Log(string.Format("Session Interval changed to {0}s", seconds));
        }

        public static void DoneAppTerminate()
        {
            if (_manager != null)
            {
                _manager.OnPause();
            }
        }

        private static void EnableTrackLocation(bool enabled)
        {
            Constants.locationEnabled = enabled;
        }

        private static void Launching()
        {
            try
            {
                SetBodyFileName();
                _manager.OnResume();
                DebugUtil.Log("OnLaunching Completed");
            }
            catch (Exception ex)
            {
                DebugUtil.Log("OnLaunching failed!", ex);
            }
        }

        private static void Pause()
        {
            try
            {
                _manager.OnPause();
                UmengSettings.Save();
                DebugUtil.Log("OnClosing Completed");
            }
            catch (Exception ex)
            {
                DebugUtil.Log("OnClosing failed!", ex);
            }
        }

        private static void UnhandledException(Exception p_exception)
        {
            try
            {
                _manager.DoneAppError(p_exception);
                UmengSettings.Save();
            }
            catch (Exception ex)
            {
                DebugUtil.Log(ex);
            }
        }

        void IAppHandler.Pause()
        {
            Pause();
        }

        void IAppHandler.UnhandledException(Exception p_exception)
        {
            UnhandledException(p_exception);
        }

        void IAppHandler.Launching()
        {
            Launching();
        }

        //private static void OnLaunching(object sender, LaunchingEventArgs e)
        //{
        //    try
        //    {
        //        UmengAnalytics.SetBodyFileName();
        //        UmengAnalytics._manager.OnResume();
        //        DebugUtil.Log("OnLaunching Completed");
        //    }
        //    catch (Exception e2)
        //    {
        //        DebugUtil.Log("OnLaunching failed!", e2);
        //    }
        //}

        //private static void OnActivated(object source, ActivatedEventArgs e)
        //{
        //    try
        //    {
        //        bool arg_06_0 = e.get_IsApplicationInstancePreserved();
        //        UmengAnalytics.SetBodyFileName();
        //        UmengAnalytics._manager.OnResume();
        //        DebugUtil.Log("OnActivated Completed");
        //    }
        //    catch (Exception e2)
        //    {
        //        DebugUtil.Log("OnActivated failed!", e2);
        //    }
        //}

        //private static void OnDeactivated(object source, DeactivatedEventArgs e)
        //{
        //    try
        //    {
        //        UmengAnalytics._manager.OnPause();
        //        UmengSettings.Save();
        //        DebugUtil.Log("OnDeactivated Completed");
        //    }
        //    catch (Exception e2)
        //    {
        //        DebugUtil.Log("OnDeactivated failed!", e2);
        //    }
        //}

        //private static void OnClosing(object source, ClosingEventArgs e)
        //{
        //    try
        //    {
        //        UmengAnalytics._manager.OnPause();
        //        UmengSettings.Save();
        //        DebugUtil.Log("OnClosing Completed");
        //    }
        //    catch (Exception e2)
        //    {
        //        DebugUtil.Log("OnClosing failed!", e2);
        //    }
        //}

        //private static void Application_UnhandledException(object sender, ApplicationUnhandledExceptionEventArgs e)
        //{

        //}

        public static void SetBodyFileName()
        {
            var appvar = _information.GetAppVersion().Replace(".", "_");
            string text = PathEx.GetAppDataPathWithKey(appvar);

            string text2 = UmengSettings.Get<string>("BodyFileName", null);
            if (!string.IsNullOrEmpty(text2) && text != text2)
            {
                BodyPersistentManager.Current.FileName = text2;
                BodyPersistentManager.Current.Delete();
            }
            BodyPersistentManager.Current.FileName = text;
            UmengSettings.Put("BodyFileName", text);
        }

        private static bool IsValidAppkey(string appkey)
        {
            if (string.IsNullOrEmpty(appkey))
            {
                DebugUtil.Log("apkey is null or empty");
                return false;
            }
            return true;
        }

        private static bool IsValidChannel(string[] channels)
        {
            return channels != null && channels.Length > 0 && !string.IsNullOrEmpty(channels[0]);
        }

        private static bool IsValidInput(object input)
        {
            try
            {
                if (input == null)
                {
                    DebugUtil.Log("input Object is null");
                    bool result = false;
                    return result;
                }
                if (input is string && string.IsNullOrWhiteSpace(input as string))
                {
                    DebugUtil.Log("input string is null , empty or whitespace");
                    bool result = false;
                    return result;
                }
            }
            catch (Exception)
            {
                bool result = false;
                return result;
            }
            return true;
        }

        private static bool RegisterEvents()
        {
            if (_application == null)
            {
                return false;
            }

            return _application.RegisterEvents(new UmengAnalytics());
        }

        //private static void OnExit(object sender, ExitEventArgs e)
        //{
        //    try
        //    {
        //        _manager.OnPause();
        //        UmengSettings.Save();
        //        DebugUtil.Log("OnClosing Completed");
        //    }
        //    catch (Exception e2)
        //    {
        //        DebugUtil.Log("OnClosing failed!", e2);
        //    }
        //}

        //private static void OnStartup(object sender, StartupEventArgs e)
        //{
        //    try
        //    {
        //        SetBodyFileName();
        //        _manager.OnResume();
        //        DebugUtil.Log("OnLaunching Completed");
        //    }
        //    catch (Exception e2)
        //    {
        //        DebugUtil.Log("OnLaunching failed!", e2);
        //    }
        //}

        //private static void OnDispatcherUnhandledException(object sender, DispatcherUnhandledExceptionEventArgs e)
        //{
        //    try
        //    {
        //        e.Handled = false;
        //        _manager.DoneAppError(e.Exception);
        //        UmengSettings.Save();
        //    }
        //    catch (Exception e2)
        //    {
        //        DebugUtil.Log(e2);
        //    }
        //}

        //private static void Current_UnhandledException(object sender, ApplicationUnhandledExceptionEventArgs e)
        //{
        //}

        private static void OnCheckUpdateCompleted(out bool handled, Dictionary<string, object> dic)
        {
            try
            {
                handled = false;
                if (CheckUpdateCompleted != null)
                {
                    UpdateEventArgs updateEventArgs = new UpdateEventArgs(dic);
                    CheckUpdateCompleted(0, updateEventArgs);
                    handled = updateEventArgs.Handled;
                }
            }
            catch (Exception e)
            {
                handled = false;
                DebugUtil.Log(e);
            }
        }

        private static void OnlineParamCallback(Dictionary<string, string> onlineParams)
        {
            try
            {
                if (UpdateOnlineParamCompleted != null)
                {
                    OnlineParamEventArgs e = new OnlineParamEventArgs(onlineParams);
                    UpdateOnlineParamCompleted(0, e);
                }
            }
            catch (Exception e2)
            {
                DebugUtil.Log(e2);
            }
        }
    }
}
